package openase.audio;

import java.nio.ByteOrder;

import openase.audio.AudioFormat;


public class AudioFormat  {

    private float sampleRate;
    private int sampleSizeInBits;
    private int channelCount;
    private boolean signed;
    private ByteOrder byteOrder;

    public AudioFormat(float sampleRate, int sampleSizeInBits, int channelCount, boolean signed, ByteOrder byteOrder) {
        this.sampleRate = sampleRate;
        this.sampleSizeInBits = sampleSizeInBits;
        this.channelCount = channelCount;
        this.signed = signed;
        this.byteOrder = byteOrder;
    }

    public float getSampleRate() {
        return sampleRate;
    }

    public int getSampleSizeInBits() {
        return sampleSizeInBits;
    }

    public int getChannelCount() {
        return channelCount;
    }

    public int getFrameSize() {
        return calculateFrameSize(channelCount, sampleSizeInBits);
    }

    public boolean isSigned() {
        return signed;
    }

    public ByteOrder getByteOrder() {
        return byteOrder;
    }
    
    public AudioFormat withSampleRate(float newSampleRate) {
        return new AudioFormat(newSampleRate, sampleSizeInBits, channelCount, signed, byteOrder);
    }
    
    public AudioFormat withSampleSizeInBits(int newSampleSizeInBits) {
        return new AudioFormat(sampleRate, newSampleSizeInBits, channelCount, signed, byteOrder);
    }
    
    public AudioFormat withChannelCount(int newChannelCount) {
        return new AudioFormat(sampleRate, sampleSizeInBits, newChannelCount, signed, byteOrder);
    }
    
    public AudioFormat withSigned(boolean newIsSigned) {
        return new AudioFormat(sampleRate, sampleSizeInBits, channelCount, newIsSigned, byteOrder);
    }

    public AudioFormat withByteOrder(ByteOrder newByteOrder) {
        return new AudioFormat(sampleRate, sampleSizeInBits, channelCount, signed, newByteOrder);
    }

    private static int calculateFrameSize(int nChannels, int nSampleSizeInBits) {
        return ((nSampleSizeInBits + 7) / 8) * nChannels;
    }

    
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((byteOrder == ByteOrder.BIG_ENDIAN) ? 31 : 17);
        result = prime * result + channelCount;
        result = prime * result + Float.floatToIntBits(sampleRate);
        result = prime * result + sampleSizeInBits;
        result = prime * result + (signed ? 1231 : 1237);
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        AudioFormat other = (AudioFormat) obj;
        if (byteOrder == null) {
            if (other.byteOrder != null)
                return false;
        } else if (byteOrder!=other.byteOrder)
            return false;
        if (channelCount != other.channelCount)
            return false;
        if (Float.floatToIntBits(sampleRate) != Float.floatToIntBits(other.sampleRate))
            return false;
        if (sampleSizeInBits != other.sampleSizeInBits)
            return false;
        if (signed != other.signed)
            return false;
        return true;
    }

    @Override
    public String toString() {
        String channels = channelCount + (channelCount == 1 ? " (mono)" : (channelCount==2 ? " (stereo)" : ""));
        return "AudioFormat [sampleRate=" + sampleRate + ", sampleSizeInBits=" + sampleSizeInBits + ", channelCount=" + channels + ", signed=" + signed + ", byteOrder=" + byteOrder + "]";
    }

}
